﻿using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Organized
{
    // Applies a post processing effect to a texture or the frame buffer
    public class PostProcessor : Component, I2DComponent
    {
        // The post processor fx file
        public Effect Effect;

        // Width and height the the render target/frame buffer
        protected int Width;
        protected int Height;
        public bool ShaderEnabled = true;
        // Texture that will processed
        Texture2D input;

        public Texture2D Input
        {
            get { return input; }
            set
            {
                input = value;               
            }
        }

        // Draw rectangle
        public Rectangle Rectangle { get { return new Rectangle(0, 0, Width, Height); } set { this.Width = value.Width; this.Height = value.Height; } }

        public PostProcessor()
            : base()
        {
            Setup(null, Engine.GraphicsDevice.Viewport.Width, Engine.GraphicsDevice.Viewport.Height);
        }

        public PostProcessor(Effect Effect, int Width, int Height)
            : base()
        {
            Setup(Effect, Width, Height);
        }

        public PostProcessor(Effect Effect, int Width, int Height, GameScreen Parent)
            : base(Parent)
        {
            Setup(Effect, Width, Height);
        }

        // Set the effect, width, and height, and inititalize the Input texture
        void Setup(Effect Effect, int Width, int Height)
        {
            this.Effect = Effect;
            Input = new Texture2D(Engine.GraphicsDevice, 1, 1);
            Input.SetData<Color>(new Color[] { Color.Black });
            this.Width = Width;
            this.Height = Height;
        }

        // Gets the current scene texture from the frame buffer
        public void GetInputFromFrameBuffer()
        {
            // Make sure we are working with a resolve texture
            if (!(Input is ResolveTexture2D))
                Input = GraphicsUtil.CreateResolveTexture();

            // Then resolve the frame buffer to the Input texture
            Engine.GraphicsDevice.ResolveBackBuffer((ResolveTexture2D)Input);
        }

        public void DrawWith(Texture2D texture)
        {
            Engine.GraphicsDevice.Clear(Color.Black);
            Engine.SpriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);

            if (ShaderEnabled)
            {
                Effect.Begin();

                // For each pass...
                foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    // Draw the input texture with the effect applied
                    Engine.SpriteBatch.Draw(texture, Rectangle, Color.White);
                    pass.End();
                }

                Effect.End();
            }
            else
            {

                // Draw the input texture with the effect applied
                Engine.SpriteBatch.Draw(texture, Rectangle, Color.White);


            }
            
            Engine.SpriteBatch.End();

            
        }

      

        public override void Draw()
        {
            Engine.GraphicsDevice.Clear(Color.Black);

            // Begin in a mode that will overrite everything and draw immediately
            Engine.SpriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);

            if (ShaderEnabled)
            {
                Effect.Begin();

                // For each pass...
                foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    // Draw the input texture with the effect applied
                    Engine.SpriteBatch.Draw(Input, Rectangle, Color.White);
                    pass.End();
                }

                Effect.End();
            }
            else
            {
              
                // Draw the input texture with the effect applied
                Engine.SpriteBatch.Draw(Input, Rectangle, Color.White);
                

            }
            Engine.SpriteBatch.End();

            base.Draw();
        }
    }
}